package com.holystone.orca.sys.aop;
import java.lang.reflect.Method;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.holystone.orca.sys.common.SystemConstant;
import com.holystone.orca.sys.model.StaffVO;
import com.holystone.orca.sys.service.ISysOperationLogService;
  
/**
 *   
 * @author huangjc
 *
 */
@Aspect  
@Component  
public  class SystemLogAspect {  
    //注入Service用于把日志保存数据库  
	@Resource(name="sysOperationLogService")
	private ISysOperationLogService sysOperationLogService;  
    //本地异常日志记录对象  
     private  static  final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class);  
  
    //Service层切点  
    @Pointcut("@annotation(com.holystone.orca.sys.aop.SystemServiceLog)")  
     public  void serviceAspect() {  
    }  
  
    //Controller层切点  
    @Pointcut("@annotation(com.holystone.orca.sys.aop.SystemControllerLog)")  
     public  void controllerAspect() {  
    }  
    
  //Controller层切点  
    @Pointcut("@annotation(com.holystone.orca.sys.aop.SystemControllerBeforeLog)")  
     public  void controllerBeforeAspect() {  
    } 
  
    /** 
     * 前置通知 用于拦截Controller层记录用户的操作 
     * 
     * @param joinPoint 切点 
     */  
    @AfterReturning("controllerAspect()")  
     public  void doAfterReturning(JoinPoint joinPoint) {  
  
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();  
        HttpSession session = request.getSession(); 
        //读取session中的用户  
        StaffVO staffVO = (StaffVO) session.getAttribute(SystemConstant.SESSION_STAFF_KEY);  
        
        //请求的IP  
        String ip = request.getRemoteAddr();  
         try {  
            //*========控制台输出=========*//  
//            System.out.println("=====返回后通知开始=====");  
//            System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  
//            System.out.println("方法描述:" + getControllerMethodDescription(joinPoint));  
//            System.out.println("请求人:" + staffVO.getPersonCode());  
//            System.out.println("请求IP:" + ip);  
//            System.out.println("=====返回后通知结束=====");  
            sysOperationLogService.addOperationLog(staffVO.getPersonCode(), ip,getControllerMethodDescription(joinPoint), session.getId(),(joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()") );
        }  catch (Exception e) {  
            //记录本地异常日志  
            logger.error("==返回后通知异常==");  
            logger.error("异常信息:{}", e.getMessage());  
        }  
    }  
    
    
    @Before("controllerBeforeAspect()")  
    public  void controllerBefore(JoinPoint joinPoint) {  
 
       HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();  
       HttpSession session = request.getSession(); 
       //读取session中的用户  
       StaffVO staffVO = (StaffVO) session.getAttribute(SystemConstant.SESSION_STAFF_KEY);  
       
       //请求的IP  
       String ip = request.getRemoteAddr();  
        try {  
           //*========控制台输出=========*//  
//           System.out.println("=====前置通知开始=====");  
//           System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));  
//           System.out.println("方法描述:" + getControllerBeforeMethodDescription(joinPoint));  
//           System.out.println("请求人:" + staffVO.getPersonCode());  
//           System.out.println("请求IP:" + ip);  
//           System.out.println("=====前置通知结束=====");  
           sysOperationLogService.addOperationLog(staffVO.getPersonCode(), ip,getControllerBeforeMethodDescription(joinPoint), session.getId(),(joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()") );
       }  catch (Exception e) {  
           //记录本地异常日志  
           logger.error("==前置通知异常==");  
           logger.error("异常信息:{}", e.getMessage());  
       }  
   }  
  
    /** 
     * 前置通知 用于拦截service层记录用户的操作  
     * 
     * @param joinPoint 
     * @param e 
     */  
    /**  
     * 异常通知 用于拦截service层记录异常日志  
     *  
     * @param joinPoint  
     * @param e  
     */    
    @AfterThrowing(pointcut = "serviceAspect()", throwing = "e")    
     public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {    
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();    
        HttpSession session = request.getSession();    
        //读取session中的用户    
        StaffVO staffVO = (StaffVO) session.getAttribute(SystemConstant.SESSION_STAFF_KEY);  
        //获取请求ip    
        String ip = request.getRemoteAddr();    
        //获取用户请求方法的参数并序列化为JSON格式字符串    
         try {    
              /*========控制台输出=========*/    
//            System.out.println("=====异常通知开始=====");    
//            System.out.println("异常代码:" + e.getClass().getName());    
//            System.out.println("异常信息:" + e.getMessage());    
//            System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    
//            System.out.println("方法描述:" + getServiceMthodDescription(joinPoint));    
//            System.out.println("请求人:" + staffVO.getPersonCode());    
//            System.out.println("请求IP:" + ip);    
               /*==========数据库日志=========*/    
            //保存数据库    
            sysOperationLogService.addOperationLog(staffVO.getPersonCode(),ip, getServiceMthodDescription(joinPoint), session.getId(),(joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")); 
            //System.out.println("=====异常通知结束=====");    
        }  catch (Exception ex) {    
            //记录本地异常日志    
            logger.error("==异常通知异常==");    
            logger.error("异常信息:{}", ex.getMessage());    
        }    
         /*==========记录本地异常日志==========*/    
        //logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage());
    
    }   
  
  
    /** 
     * 获取注解中对方法的描述信息 用于service层注解 
     * 
     * @param joinPoint 切点 
     * @return 方法描述 
     * @throws Exception 
     */  
     public  static String getServiceMthodDescription(JoinPoint joinPoint)  
             throws Exception {  
        String targetName = joinPoint.getTarget().getClass().getName();  
        String methodName = joinPoint.getSignature().getName();  
        Object[] arguments = joinPoint.getArgs();  
        Class targetClass = Class.forName(targetName);  
        Method[] methods = targetClass.getMethods();  
        String description = "";  
         for (Method method : methods) {  
             if (method.getName().equals(methodName)) {  
                Class[] clazzs = method.getParameterTypes();  
                 if (clazzs.length == arguments.length) {  
                    description = method.getAnnotation(SystemServiceLog. class).description();  
                     break;  
                }  
            }  
        }  
         return description;  
    }  
  
    /** 
     * 获取注解中对方法的描述信息 用于Controller层注解 
     * 
     * @param joinPoint 切点 
     * @return 方法描述 
     * @throws Exception 
     */  
     public  static String getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {  
        String targetName = joinPoint.getTarget().getClass().getName();  
        String methodName = joinPoint.getSignature().getName();  
        Object[] arguments = joinPoint.getArgs();  
        Class targetClass = Class.forName(targetName);  
        Method[] methods = targetClass.getMethods();  
        String description = "";  
         for (Method method : methods) {  
             if (method.getName().equals(methodName)) {  
                Class[] clazzs = method.getParameterTypes();  
                 if (clazzs.length == arguments.length) {  
                    description = method.getAnnotation(SystemControllerLog. class).description();  
                     break;  
                }  
            }  
        }  
         return description;  
    }  
     
     
     public  static String getControllerBeforeMethodDescription(JoinPoint joinPoint)  throws Exception {  
         String targetName = joinPoint.getTarget().getClass().getName();  
         String methodName = joinPoint.getSignature().getName();  
         Object[] arguments = joinPoint.getArgs();  
         Class targetClass = Class.forName(targetName);  
         Method[] methods = targetClass.getMethods();  
         String description = "";  
          for (Method method : methods) {  
              if (method.getName().equals(methodName)) {  
                 Class[] clazzs = method.getParameterTypes();  
                  if (clazzs.length == arguments.length) {  
                     description = method.getAnnotation(SystemControllerBeforeLog. class).description();  
                      break;  
                 }  
             }  
         }  
          return description;  
     }  
}  